/*
任务管理类, 用于接收来自客户端的任务请求, 缓存任务并按照通信协议解析, 逐个交付给任务执行层
接收来自任务执行层的执行结果, 按照协议响应给客户端
*/
#ifndef TASK_MANAGER_H
#define TASK_MANAGER_H
#include "../includes/IPC.h"
#include <queue>
#include <mutex>
#include <string> // 添加 string 头文件
#include <sstream> 

class TaskManager{
public:
    // 全局单例类
    static TaskManager& getInstance(); // 获取全局单例的方法, 首次调用时需要传入磁盘文件路径
    ~TaskManager(); // 析构函数
    // 禁止拷贝和移动
    TaskManager(const TaskManager&) = delete;
    TaskManager& operator=(const TaskManager&) = delete;
    TaskManager(TaskManager&&) = delete;
    TaskManager& operator=(TaskManager&&) = delete;

public:

    // 任务结构体
    struct WriteTask{
        int task_id; // 用于唯一标识一个任务
        int type;
        char file_name[129]; // 文件名，最大128字节+1字节结束符
        size_t write_size; // 写入长度 (表示实际需要从 buf 指向的内存中读取多少字节)
        char* buf; // 指向待写入内容的指针

        // 默认构造函数：初始化所有成员，buf 为 nullptr
        WriteTask() : task_id(0), type(-1), write_size(0), buf(nullptr) {
            file_name[0] = '\0'; // 初始化文件名
        }

        // 析构函数：安全释放 buf 指向的内存
        ~WriteTask() {
            delete[] buf; // delete[] 会检查 buf 是否为 nullptr，如果是则无操作
        }

        // 禁用拷贝构造和拷贝赋值，因为它们涉及到指针，需要深拷贝逻辑
        WriteTask(const WriteTask&) = delete;
        WriteTask& operator=(const WriteTask&) = delete;

        // --- 序列化/反序列化方法 ---
        static void from_string(const std::string &task_str, WriteTask &task) {
            size_t offset = 0;
            
            // 读取任务ID (4字节)
            if(task_str.size() < 7) return; // 长度不够 (至少需要4+1+1+1+4)
            task.task_id = *(reinterpret_cast<const int*>(task_str.data() + offset));
            offset += 4;
            
            task.type = static_cast<int>(task_str[offset]);
            offset += 1;
            
            unsigned char file_name_len = static_cast<unsigned char>(task_str[offset]);
            offset += 1;
            
            if(offset + file_name_len + 4 <= task_str.size()) { // +4 for content length
                // 读取文件名
                if(file_name_len > 0 && file_name_len <= 128) {
                    std::string temp_name = task_str.substr(offset, file_name_len);
                    std::strncpy(task.file_name, temp_name.c_str(), 128);
                    task.file_name[file_name_len] = '\0';
                }
                offset += file_name_len;
                
                // 读取写入内容长度 (4字节int)
                size_t new_write_size = static_cast<size_t>(*(reinterpret_cast<const int*>(task_str.data() + offset)));
                offset += 4;

                // 动态分配内存 ---
                // 检查 task.buf 是否已经分配了内存，如果已分配则先释放
                if (task.buf != nullptr) {
                    delete[] task.buf; 
                }
                // 根据协议限制，实际分配的大小不应超过 1024
                size_t actual_alloc_size = std::min(new_write_size, static_cast<size_t>(1024));
                task.buf = new char[actual_alloc_size]; 
                task.write_size = actual_alloc_size; // 更新结构体中的 write_size 为实际分配的大小
                
                // 读取写入内容
                if(offset + actual_alloc_size <= task_str.size()) {
                    std::string content = task_str.substr(offset, actual_alloc_size);
                    std::memcpy(task.buf, content.c_str(), actual_alloc_size);
                } else { // 实际内容小于理论写入长度, 异常情况
                    // 清空已分配的内存
                    delete[] task.buf;
                    task.buf = nullptr;
                    task.write_size = 0;
                    return; // 或者抛出异常
                }
            }
        }

        static void to_string(const WriteTask& task, std::string &task_str) {
            task_str = "";
            
            // 添加任务ID (4字节)
            task_str.append(reinterpret_cast<const char*>(&task.task_id), 4);
            
            // 添加任务类型
            task_str += static_cast<char>(task.type);
            
            // 添加文件名长度
            size_t file_name_len = std::strlen(task.file_name);
            unsigned char len_byte = static_cast<unsigned char>(std::min(file_name_len, static_cast<size_t>(128)));
            task_str += static_cast<char>(len_byte);
            
            // 添加文件名
            task_str.append(task.file_name, len_byte);
            
            // 添加写入内容长度 (4字节)
            // 使用 write_size 作为要序列化的长度
            int content_len = static_cast<int>(std::min(task.write_size, static_cast<size_t>(1024)));
            task_str.append(reinterpret_cast<const char*>(&content_len), 4);
            
            // 添加写入内容 (从 buf 指针)
            // 需要检查 buf 是否为 nullptr
            if (task.buf != nullptr) {
                size_t actual_write_size = std::min(task.write_size, static_cast<size_t>(1024));
                task_str.append(task.buf, actual_write_size);
            } 
        }
    };

    struct CatTask{
        int task_id; // 用于唯一标识一个任务
        int type;
        char file_name[129]; // 文件名，最大128字节+1字节结束符

        // --- 序列化/反序列化方法 ---
        static void from_string(const std::string &task_str, CatTask &task) {
            size_t offset = 0;
            // 读取任务ID (4字节)
            if(task_str.size() < 6) return; // 长度不够
            task.task_id = *(reinterpret_cast<const int*>(task_str.data() + offset));
            offset += 4;
            
            task.type = static_cast<int>(task_str[offset]);
            offset += 1;
            
            unsigned char file_name_len = static_cast<unsigned char>(task_str[offset]);
            offset += 1;
            
            if(offset + file_name_len <= task_str.size() && file_name_len <= 128) {
                std::string temp_name = task_str.substr(offset, file_name_len);
                std::strncpy(task.file_name, temp_name.c_str(), 128);
                task.file_name[file_name_len] = '\0';
            }
        }

        static void to_string(const CatTask& task, std::string &task_str) {
            task_str = "";
            
            // 添加任务ID (4字节)
            task_str.append(reinterpret_cast<const char*>(&task.task_id), 4);
            
            // 添加任务类型
            task_str += static_cast<char>(task.type);
            
            // 添加文件名长度
            size_t file_name_len = std::strlen(task.file_name);
            unsigned char len_byte = static_cast<unsigned char>(std::min(file_name_len, static_cast<size_t>(128)));
            task_str += static_cast<char>(len_byte);
            
            // 添加文件名
            task_str.append(task.file_name, len_byte);
        }
    };

    struct TouchTask{
        int task_id; // 用于唯一标识一个任务
        int type;
        char file_name[129]; // 文件名，最大128字节+1字节结束符

        // --- 序列化/反序列化方法 ---
        static void from_string(const std::string &task_str, TouchTask &task) {
            size_t offset = 0;
            // 读取任务ID (4字节)
            if(task_str.size() < 6) return; // 长度不够
            task.task_id = *(reinterpret_cast<const int*>(task_str.data() + offset));
            offset += 4;
            
            task.type = static_cast<int>(task_str[offset]);
            offset += 1;
            
            unsigned char file_name_len = static_cast<unsigned char>(task_str[offset]);
            offset += 1;
            
            if(offset + file_name_len <= task_str.size() && file_name_len <= 128) {
                std::string temp_name = task_str.substr(offset, file_name_len);
                std::strncpy(task.file_name, temp_name.c_str(), 128);
                task.file_name[file_name_len] = '\0';
            }
        }

        static void to_string(const TouchTask& task, std::string &task_str) {
            task_str = "";
            
            // 添加任务ID (4字节)
            task_str.append(reinterpret_cast<const char*>(&task.task_id), 4);
            
            // 添加任务类型
            task_str += static_cast<char>(task.type);
            
            // 添加文件名长度
            size_t file_name_len = std::strlen(task.file_name);
            unsigned char len_byte = static_cast<unsigned char>(std::min(file_name_len, static_cast<size_t>(128)));
            task_str += static_cast<char>(len_byte);
            
            // 添加文件名
            task_str.append(task.file_name, len_byte);
        }
    };

    struct RmTask{
        int task_id; // 用于唯一标识一个任务
        int type;
        char file_name[129]; // 文件名，最大128字节+1字节结束符

        // --- 序列化/反序列化方法 ---
        static void from_string(const std::string &task_str, RmTask &task) {
            size_t offset = 0;
            // 读取任务ID (4字节)
            if(task_str.size() < 6) return; // 长度不够
            task.task_id = *(reinterpret_cast<const int*>(task_str.data() + offset));
            offset += 4;
            
            task.type = static_cast<int>(task_str[offset]);
            offset += 1;
            
            unsigned char file_name_len = static_cast<unsigned char>(task_str[offset]);
            offset += 1;
            
            if(offset + file_name_len <= task_str.size() && file_name_len <= 128) {
                std::string temp_name = task_str.substr(offset, file_name_len);
                std::strncpy(task.file_name, temp_name.c_str(), 128);
                task.file_name[file_name_len] = '\0';
            }
        }

        static void to_string(const RmTask& task, std::string &task_str) {
            task_str = "";
            
            // 添加任务ID (4字节)
            task_str.append(reinterpret_cast<const char*>(&task.task_id), 4);
            
            // 添加任务类型
            task_str += static_cast<char>(task.type);
            
            // 添加文件名长度
            size_t file_name_len = std::strlen(task.file_name);
            unsigned char len_byte = static_cast<unsigned char>(std::min(file_name_len, static_cast<size_t>(128)));
            task_str += static_cast<char>(len_byte);
            
            // 添加文件名
            task_str.append(task.file_name, len_byte);
        }
    };

    struct LsTask{
        int task_id; // 用于唯一标识一个任务
        int type;

        // --- 序列化/反序列化方法 ---
        static void from_string(const std::string &task_str, LsTask &task) {
            size_t offset = 0;
            // 读取任务ID (4字节)
            if(task_str.size() < 5) return; // 长度不够
            task.task_id = *(reinterpret_cast<const int*>(task_str.data() + offset));
            offset += 4;
            
            task.type = static_cast<int>(task_str[offset]);
        }

        static void to_string(const LsTask& task, std::string &task_str) {
            task_str = "";
            
            // 添加任务ID (4字节)
            task_str.append(reinterpret_cast<const char*>(&task.task_id), 4);
            
            // 添加任务类型
            task_str += static_cast<char>(task.type);
        }
    };

    // 任务响应结构体
    struct WriteResponse{
        int task_id; // 用于唯一标识一个任务
        int type;
        char status_code; // 任务执行状态码(0:失败, 1:成功)
        int bytes_written; // 成功写入的字节数

        // --- 序列化/反序列化方法 ---
        static void from_string(const std::string& resp_str, WriteResponse& resp) {
            size_t offset = 0;

            // 检查长度是否足够 (4字节ID + 1字节类型 + 1字节status_code + 4字节bytes_written)
            if (resp_str.size() < 10) return; 

            resp.task_id = *(reinterpret_cast<const int*>(resp_str.data() + offset));
            offset += 4;

            resp.type = static_cast<int>(resp_str[offset]);
            offset += 1;

            resp.status_code = static_cast<char>(resp_str[offset]);
            offset += 1;

            resp.bytes_written = *(reinterpret_cast<const int*>(resp_str.data() + offset));
            // offset += 4; // 读取完最后一个字段，不需要再移动
        }

        static void to_string(const WriteResponse& resp, std::string& resp_str) {
            resp_str = "";

            resp_str.append(reinterpret_cast<const char*>(&resp.task_id), 4);
            resp_str += static_cast<char>(resp.type);
            resp_str += static_cast<char>(resp.status_code);
            resp_str.append(reinterpret_cast<const char*>(&resp.bytes_written), 4);
        }
    };

    struct CatResponse{
        int task_id; // 用于唯一标识一个任务
        int type;
        char status_code; // 任务执行状态码(0:失败, 1:成功)
        int content_length; // 读取的文件内容长度 (表示实际存储在 content 指向的内存中的字节数)
        char* content; // 指向文件内容的指针

        // 默认构造函数：初始化所有成员，content 为 nullptr
        CatResponse() : task_id(0), type(-1), content_length(0), content(nullptr) {
        }

        // 析构函数：安全释放 content 指向的内存
        ~CatResponse() {
            delete[] content; // delete[] 会检查 content 是否为 nullptr，如果是则无操作
        }

        // 禁用拷贝构造和拷贝赋值
        CatResponse(const CatResponse&) = delete;
        CatResponse& operator=(const CatResponse&) = delete;

        // --- 序列化/反序列化方法 ---
        static void from_string(const std::string& resp_str, CatResponse& resp) {
            size_t offset = 0;

            // 检查长度是否足够 (4字节ID + 1字节类型 + 1字节status_code + 4字节content_length + 至少1字节内容)
            if (resp_str.size() < 11) return; 

            resp.task_id = *(reinterpret_cast<const int*>(resp_str.data() + offset));
            offset += 4;

            resp.type = static_cast<int>(resp_str[offset]);
            offset += 1;

            resp.status_code = static_cast<char>(resp_str[offset]);
            offset += 1;

            int new_content_length = *(reinterpret_cast<const int*>(resp_str.data() + offset));
            offset += 4;

            // --- 核心修改：动态分配内存 ---
            // 检查 resp.content 是否已经分配了内存，如果已分配则先释放
            if (resp.content != nullptr) {
                delete[] resp.content;
            }
            // 根据协议限制，实际分配的大小不应超过 256 * 1024
            size_t actual_alloc_size = std::min(
                static_cast<size_t>(new_content_length),
                static_cast<size_t>(256 * 1024)
            );
            resp.content = new char[actual_alloc_size]; 
            resp.content_length = actual_alloc_size; // 更新结构体中的 content_length 为实际分配的大小

            // 读取文件内容
            if (offset + actual_alloc_size <= resp_str.size()) {
                std::string content_data = resp_str.substr(offset, actual_alloc_size);
                std::memcpy(resp.content, content_data.c_str(), actual_alloc_size);
            } else {
                // 如果 resp_str 中的内容长度不足以满足 content_length, 清空已分配的内存
                delete[] resp.content;
                resp.content = nullptr;
                resp.content_length = 0;
                return;
            }
        }

        static void to_string(const CatResponse& resp, std::string& resp_str) {
            resp_str = "";

            resp_str.append(reinterpret_cast<const char*>(&resp.task_id), 4);
            resp_str += static_cast<char>(resp.type);
            resp_str += static_cast<char>(resp.status_code);
            resp_str.append(reinterpret_cast<const char*>(&resp.content_length), 4);

            // 使用 content 指针 ---
            size_t content_to_write = std::min(
                static_cast<size_t>(resp.content_length),
                static_cast<size_t>(256 * 1024) // 不能超过协议定义的最大长度
            );
            // 需要检查 content 是否为 nullptr
            if (resp.content != nullptr) {
                resp_str.append(resp.content, content_to_write);
            } 
        }
    };

    struct TouchResponse{
        int task_id; // 用于唯一标识一个任务
        int type;
        char status_code; // 任务执行状态码(0:失败, 1:成功)

        // --- 序列化/反序列化方法 ---
        static void from_string(const std::string& resp_str, TouchResponse& resp) {
            size_t offset = 0;

            // 检查长度是否足够 (4字节ID + 1字节类型 + 1字节status_code)
            if (resp_str.size() < 6) return; 

            resp.task_id = *(reinterpret_cast<const int*>(resp_str.data() + offset));
            offset += 4;

            resp.type = static_cast<int>(resp_str[offset]);
            offset += 1;

            resp.status_code = static_cast<char>(resp_str[offset]);
            // offset += 1; // 读取完最后一个字段，不需要再移动
        }

        static void to_string(const TouchResponse& resp, std::string& resp_str) {
            resp_str = "";

            resp_str.append(reinterpret_cast<const char*>(&resp.task_id), 4);
            resp_str += static_cast<char>(resp.type);
            resp_str += static_cast<char>(resp.status_code);
        }
    };

    struct RmResponse{
        int task_id; // 用于唯一标识一个任务
        int type;
        char status_code; // 任务执行状态码(0:失败, 1:成功)

        // --- 序列化/反序列化方法 ---
        static void from_string(const std::string& resp_str, RmResponse& resp) {
            size_t offset = 0;

            // 检查长度是否足够 (4字节ID + 1字节类型 + 1字节status_code)
            if (resp_str.size() < 6) return; 

            resp.task_id = *(reinterpret_cast<const int*>(resp_str.data() + offset));
            offset += 4;

            resp.type = static_cast<int>(resp_str[offset]);
            offset += 1;

            resp.status_code = static_cast<char>(resp_str[offset]);
            // offset += 1; // 读取完最后一个字段，不需要再移动
        }

        static void to_string(const RmResponse& resp, std::string& resp_str) {
            resp_str = "";

            resp_str.append(reinterpret_cast<const char*>(&resp.task_id), 4);
            resp_str += static_cast<char>(resp.type);
            resp_str += static_cast<char>(resp.status_code);
        }
    };

    struct LsResponse{
        int task_id; // 用于唯一标识一个任务
        int type;
        char status_code; // 任务执行状态码(0:失败, 1:成功)
        char file_count; // 文件个数
        static const int MAX_FILES = 96; // 最大文件数量
        char* file_entries[MAX_FILES]; // 指针数组，每个指针指向一个文件名字符串

        // 默认构造函数：初始化所有成员，所有指针为 nullptr
        LsResponse() : task_id(0), type(-1), file_count(0) {
            for(int i = 0; i < MAX_FILES; ++i) {
                file_entries[i] = nullptr;
            }
        }

        void clear(){
            for(int i = 0; i < MAX_FILES; ++i) {
                if(file_entries[i] != nullptr) {
                    delete[] file_entries[i];
                    file_entries[i] = nullptr; // 保险起见，清空指针
                }
            }
        }

        // 析构函数：释放所有指针指向的内存
        ~LsResponse() {
            clear();
        }

        // 禁用拷贝构造和拷贝赋值，因为它们涉及到指针数组，需要深拷贝逻辑
        LsResponse(const LsResponse&) = delete;
        LsResponse& operator=(const LsResponse&) = delete;

        // --- 序列化/反序列化方法 ---
        static void from_string(const std::string& resp_str, LsResponse& resp) {
            size_t offset = 0;

            // 检查长度是否足够 (4字节ID + 1字节类型 + 1字节status_code + 1字节file_count + 至少0字节entries)
            if (resp_str.size() < 7) return; 

            resp.task_id = *(reinterpret_cast<const int*>(resp_str.data() + offset));
            offset += 4;

            resp.type = static_cast<int>(resp_str[offset]);
            offset += 1;

            resp.status_code = static_cast<char>(resp_str[offset]);
            offset += 1;

            char expected_file_count = static_cast<char>(resp_str[offset]);
            offset += 1;

            // 读取文件项条目 (以 \n 分隔的字符串)
            std::string entries_data = resp_str.substr(offset);
            std::istringstream iss(entries_data);
            std::string file_name;
            int parsed_count = 0;

            // 清空 resp 中已有的文件名
            resp.clear(); 

            while (std::getline(iss, file_name) && parsed_count < LsResponse::MAX_FILES) {
                // 检查文件名长度是否超限 (128 字节 + 1 字节结束符)
                if (file_name.length() <= 128) {
                    // 为新文件名分配内存并复制
                    char* new_name = new char[file_name.length() + 1];
                    std::strncpy(new_name, file_name.c_str(), file_name.length());
                    new_name[file_name.length()] = '\0';
                    resp.file_entries[parsed_count] = new_name;
                    parsed_count++;
                }
            }

            resp.file_count = parsed_count;
        }

        static void to_string(const LsResponse& resp, std::string& resp_str) {
            resp_str = "";

            resp_str.append(reinterpret_cast<const char*>(&resp.task_id), 4);
            resp_str += static_cast<char>(resp.type);
            resp_str += static_cast<char>(resp.status_code);
            resp_str += static_cast<char>(resp.file_count);

            // 写入文件项条目 (拼接指针数组中的文件名，用 \n 分隔)
            for (int i = 0; i < resp.file_count; ++i) {
                if (resp.file_entries[i] != nullptr) {
                    resp_str += resp.file_entries[i];
                    if (i < resp.file_count - 1) { // 在最后一个文件名后不添加 \n
                        resp_str += '\n';
                    }
                }
            }
        }
    };


    // --- 任务队列相关方法 ---
    void add_task(const std::string& task_str); // 向任务队列中添加一个任务
    void get_task(std::string& task_str); // 从任务队列中取出一个任务
    bool task_empty(); // 判断任务队列是否为空 (重命名以区分)

    // --- 响应队列相关方法 ---
    void add_resp(const std::string& resp_str); // 向响应队列中添加一个响应
    void get_resp(std::string& resp_str); // 从响应队列中取出一个响应
    bool resp_empty(); // 判断响应队列是否为空

    int task_type(const std::string& task_str); // 解析某个字节流的任务类型
    int resp_type(const std::string& resp_str); // 解析某个字节流的响应类型

private:
    static std::queue<std::string> tasks; // 任务队列, 每个任务以字节流的形式存储
    static std::queue<std::string> responses; // 响应队列, 每个响应以字节流的形式存储
    static std::mutex task_mtx; // 互斥锁, 用于互斥访问任务队列
    static std::mutex resp_mtx; // 互斥锁, 用于互斥访问响应队列

private:
    TaskManager();
    static TaskManager* instance_;
};

#endif